﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;

namespace TMS
{
   
    public class Dios
    {
        #region ATRIBUTOS

        private List<Error> _LstErrores;
        private List<Aplicacion> _LstAplicaciones;
        private List<Usuario> _LstUsuarios;

        #endregion

        #region PROPERTIES

        public List<Error> LstErrores
        {
            get { return _LstErrores; }
            set { _LstErrores = value; }
        }
        public List<Aplicacion> LstAplicaciones
        {
            get { return _LstAplicaciones; }
            set { _LstAplicaciones = value; }
        }
        public List<Usuario> LstUsuarios
        {
            get { return _LstUsuarios; }
            set { _LstUsuarios = value; }
        }
        #endregion

        #region CONSTRUCTORES

        private Dios()
        {
            _LstErrores = new List<Error>();
            _LstAplicaciones = new List<Aplicacion>();
            _LstUsuarios = new List<Usuario>();

        }
        #endregion

        #region SINGLETON

        private static Dios unDios;
        public static Dios getInstancia()
        {
            if (unDios == null)
            {
                unDios = new Dios();
            }
            return unDios;
        }

        #endregion

        #region METODOS

        //Alta Usuario.
        public void activarUsuario(long pUsuarioId)
        {
            /*
             * Da el alta en el sistema al usuario cuyo Id se recibe como parametro.
             */ 
            Usuario pUsuario = Usuario.getUsuarioById(pUsuarioId);
            pUsuario.activarUsu();
        }
        
        //Revisar que el nombre de usuario no se haya utilizado ya.
        public bool existeUsuario(string pNic)
        {
            return Usuario.existeUsuario(pNic);
        }

        //registro de Usuario.
        public void regUsuario(string pNom, string pNic, string pPass, string pEMail, string pTipoUsu)
        {
            long nuevoId = Usuario.getUltimoId() + 1; //Se busca el ulTtimo Id registrado y se le suma 1.
            /* 
             * Dependiendo del tipo de usuario elegido se crea una nueva instancia del mismo 
             * y se guarda en el documento XML
             */
            switch (pTipoUsu)
            { 
                case "Administrador":
                    Administrador a = new Administrador(nuevoId, pNom, pNic, pPass, pEMail);
                    a.newAdministrador();
                    break;
                case "Tester":
                    Tester t = new Tester(nuevoId, pNom, pNic, pPass, pEMail);
                    t.newTester();
                    break;
                case "Developer":
                    Developer d = new Developer(nuevoId, pNom, pNic, pPass, pEMail);
                    d.newDeveloper();
                    break;
            }
        }
       
        //Modificar Usuario (por Usuario).
        public void modUsuarioByUsuario(long pId, string pNom, string pPass, string pEmail)
        {
            Usuario u = new Usuario(pId, pNom, pPass, pEmail);
            u.modUsuario();
        }

        //Modificar Usuario (por Administrador).
        public void modUsuario(long pId, string pNom, string pNic, string pPass, string pEMail, string pTipoUsu, string pTipoAnt)
        {
            /*
             * Se elimina al usuario del documento especializado en el que estaba registrado antes, ya sea Administradores, 
             * Developers o Testers en caso de que se haya modificado el tipo o Rol del usuario.
             */
            Usuario.removeUsuarioByTipo(pId, pTipoAnt);
            /* 
             * Dependiendo del tipo que el usuario tenga asignado se crea una nueva instancia del mismo 
             * y se guarda en el documento XML
             */
            switch (pTipoUsu)
            {
                case "Administrador":
                    Administrador a = new Administrador(pId, pNom, pNic, pPass, pEMail);
                    a.Estado = usuarioEstado.Activo;
                    a.modAdministrador();
                    break;
                case "Tester":
                    Tester t = new Tester(pId, pNom, pNic, pPass, pEMail);
                    t.Estado = usuarioEstado.Activo;
                    t.modTester();
                    break;
                case "Developer":
                    Developer d = new Developer(pId, pNom, pNic, pPass, pEMail);
                    d.Estado = usuarioEstado.Activo;
                    d.modDeveloper();
                    break;
            }
        }

        //Eliminar Usuario
        public void removeUsuario(long pUsuId)
        {
            /*
             * Desactiva el usuario cuyo Id se recibe como parametro.
             */ 
            Usuario pUsuario = Usuario.getUsuarioById(pUsuId);
            pUsuario.remUsuario();
        }

        //Listar Usuarios Activos.
        public List<Usuario> listarActivos()
        {
            return Usuario.getListActivos();
        }

        //Listar Usuarios Inactivos.
        public List<Usuario> listarInactivos()
        {
            return Usuario.getListInactivos();
        }

        //Obtener el usuario por su Id.
        public Usuario getUsuarioById(long usuId)
        {
           return Usuario.getUsuarioById(usuId);
        }

        //Listar Desarrolladores
        public List<Developer> listarDevs()
        {
            return Developer.getDevList();
        }

        //Listar todos los Usuarios
        public List<Usuario> listarUsuariosAll()
        {
            return Usuario.getListAllUsuarios();
        }

        //LogIn Usuario.
        public Usuario verificarPassword(string pNomUsu, string pPass)
        {
           return Usuario.verifPass(pNomUsu, pPass);
        }

        //Conseguir el tipo del usuario por su Id
        public string getTipoUsuario(long pId)
        {
            return Usuario.getTipoUsuario(pId);
        }

        //Registro Aplicacion.
        public void regAplicacion(string pNom, string pDesc)
        {
            long nuevoId = Aplicacion.getUltimoId() + 1; //Se busca el ultimo Id registrado y se le suma 1.
            Aplicacion a = new Aplicacion(nuevoId, pNom, pDesc); //Se crea una nueva instancia de Aplicacion y se le asignan los valores a los atributos.
            a.newAplicacion(); //Se agrega la instancia creada al archivo XML.
        }

        //Modificar Aplicacion.
        public void modAplicacion(long pId, string pNom, string pDesc)
        {
            Aplicacion a = new Aplicacion(pId, pNom, pDesc);
            a.updateAplicacion();
        }

        //Eliminar Aplicacion.
        public void removeAplicacion(long pId)
        {
            Aplicacion.removeAplicacion(pId);
        }

        //Verificar que el nombre de la aplicacion nueva no este registrada ya en el sistema.
        public bool existeApp(string pNomApp)
        {
            return Aplicacion.existeAplicacion(pNomApp);
        }

        //Listar Aplicaciones
        public List<Aplicacion> listarApps()
        {
            return Aplicacion.listApps();
        }

        //Dar aplicacion por numero de Id de la misma.
        public Aplicacion getAppById(long pIdApp)
        {
            return Aplicacion.getAppById(pIdApp);
        }

        //Dar aplicacion por nombre.
        public Aplicacion getAppByName(string pNom)
        {
            return Aplicacion.getAppByName(pNom);
        }

        //Registro Modulo
        public void regModulo(string pTipoApp, string pNom, string pDes, long pIdApp, long pDeveId)
        {
            /*
             * En el codigo siguiente se crea una nueva instancia de la clase Aplicacion,
             * a la que se le asigna el resultado de la busqueda de una aplicacion con el
             * Id suministrado por el parametro "pIdApp", luego se asigna dicha instancia 
             * al nuevo modulo.
             * Se realiza el mismo proceso tambien con el desarrollador que se asignara al 
             * nuevo modulo. 
             */

            Aplicacion ap = Aplicacion.getAppById(pIdApp);
            Developer dev = Developer.getDeveloperById(pDeveId);
            long nuevoId = Modulo.getUltimoId() + 1;
            Modulo m = new Modulo(nuevoId, pTipoApp, pNom, pDes, ap, dev);
            m.newModulo();
        }

        //Modificar Modulo.
        public void modModulo(long pId, string pTipoApp, string pNom, string pDes, long pIdApp, long pDevId)
        {
            /*
             * En el codigo siguiente se crea una nueva instancia de la clase Aplicacion,
             * a la que se le asigna el resultado de la busqueda de una aplicacion con el
             * Id suministrado por el parametro "pIdApp", luego se asigna dicha instancia 
             * al nuevo modulo.
             * Se realiza el mismo proceso tambien con el desarrollador que se asignara al 
             * modulo modificado.
             */
            Aplicacion ap = Aplicacion.getAppById(pIdApp);
            Developer dev = Developer.getDeveloperById(pDevId);
            Modulo m = new Modulo(pId, pTipoApp, pNom, pDes, ap, dev);
            m.updateModulo();
        }

        // Eliminar Modulo.
        public void removeModulo(long pModId)
        {
            Modulo.removeModulo(pModId);
        }

        // Verificar si el nombre de un modulo esta registrada en el sistema.
        public bool existeModulo(string pNomMod)
        {
            return Modulo.existeMod(pNomMod);
        }

        //Dar Modulo por Id.
        public Modulo getModById(long moId)
        {
            return Modulo.getModuloById(moId);
        }

        //Listar Modulos por Aplicacion
        public List<Modulo> listarModsByAppId(long appId)
        {
            return Modulo.getListModulosByAppId(appId);
        }

        //Alta Nuevo Error.
        public void nuevoError(string pApli, string pModu, string pDesc, string pImpor, string pUsu)
        {
            Error e = new Error();
            e.Id = Error.getUltimoId() + 1;
            e.Aplicacion = AplicacionXMLManager.getInstancia().getAplicacionByName(pApli);
            e.Modulo = ModuloXMLManager.getInstancia().getModuloByName(pModu);
            e.Descripcion = pDesc;
            e.Importancia = (tipoImportancia)Enum.Parse(typeof(tipoImportancia), pImpor);
            e.Usuario = UsuarioXMLManager.getInstancia().getUsuarioById(long.Parse(pUsu));
            e.FechaCreado = DateTime.Today;
            e.newError();

        }

        // Modificar un error.
        public void modificarError(long pId, /*string pApli, string pModu,*/ string pDesc, string pImpor, string pEstado, string pUsu)
        {
            Error e = new Error();
            e.Id = pId;
            //e.Aplicacion = AplicacionXMLManager.getInstancia().getAplicacionByName(pApli);
            //e.Modulo = ModuloXMLManager.getInstancia().getModuloByName(pModu);
            e.Descripcion = pDesc;
            e.Estado = (tipoEstado)Enum.Parse(typeof(tipoEstado), pEstado);
            e.Importancia = (tipoImportancia)Enum.Parse(typeof(tipoImportancia), pImpor);
            e.Usuario = UsuarioXMLManager.getInstancia().getUsuarioById(long.Parse(pUsu));
            //Si se modifico el estado a Cerrado...
            if (e.Estado == tipoEstado.Cerrado)
            {
                //Se guarda la fecha de cierre...
                e.FechaCerrado = DateTime.Today;
            }
            e.updateError();

        }

        //Eliminar un error.
        public void eliminarError(Error pError)
        {
            pError.removeError();
        }

        //Cerrar un error
        public void cerrarError(Error pError)
        {
            pError.cerrarError();
        }

        //Listar errores por usuario.
        public List<Error> listarErroresByUsuario(long pId)
        {
            return Error.getErrListByUserId(pId);
        }

        //Dar error por Id del mismo.
        public Error getErrorById(long pErrId)
        {
            //Recupera un Error por su Id y le asigna la lista de comentarios relacionados.
            Error e = Error.getErrorById(pErrId);
            e.LstComentarios = getCommentsByErrId(e.Id);
            return e;
        }

        //Dar lista de errores por fecha de CERRADO.
        public List<Error> getLstErrByFechCerr(DateTime fech1, DateTime fech2)
        {
            return Error.getListaErrByFechaCerrado(fech1, fech2);
        }

        //Dar lista de errores por fecha de CREADO.
        public List<Error> getLstErrByFechCre(DateTime fech1, DateTime fech2)
        {
            return Error.getListaErrByFechaCreado(fech1, fech2);
        }

        //Dar lista de errores por IMPORTANCIA.
        public List<Error> getLstErrByImportancia(string pImpor)
        {
            return Error.getListaErrByImportancia(pImpor);
        }

        //Dar lista de errores por ESTADO.
        public List<Error> getLstErrByEstado(string pEstado)
        {
            return Error.getListaErrByEstado(pEstado);
        }

        //Dar lista de errores por ID DE LA APLICACION.
        public List<Error> getLstErrByAppId(long pId)
        {
            return Error.getListaErrByAppId(pId);
        }

        //Dar lista de errores por ID DE UN MODULO.
        public List<Error> getLstErrByModId(long pId)
        {
            return Error.getListaErrByModId(pId);
        }

        //Dar Estadisticas de errores por estado e Id de aplicacion
        public List<float> getEstadByAppId(long pId, string pEst)
        {
            return Error.getEstadByAppId(pId, pEst);
        }

        //Encontrar para asignarselos a un error, los comentarios relacionados por su Id.
        public List<ComentarioError> getCommentsByErrId(long errId)
        {
            return Error.listarComentarios(errId);
        }

        //Nuevo comentario
        public void addComentario(long pErrId, string pComentario, long idUsu)
        {
            ComentarioError cE = new ComentarioError();
            cE.Id = ComentarioError.getUltimoId() + 1;
            cE.Comentario = pComentario;
            cE.Fecha = DateTime.Today;
            cE.Usuario = Usuario.getUsuarioById(idUsu);
            cE.newComentario(pErrId);
        }

        //Modificar comentario.
        public void modComentario(long pErrId, long comId, string pComentario)
        {
            ComentarioError cE = new ComentarioError();
            cE.Id = comId;
            cE.Comentario = pComentario;
            cE.modComentario(pErrId);
        }

        //Dar comentario por su Id.
        public ComentarioError getCommentById(long pId)
        {
            return ComentarioError.getCommentById(pId);
        }
       
        #endregion
    }
}